<template>
    <div>
        <div id="container"></div>
    </div>
</template>

<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
// 引入渲染器通道RenderPass
import { OutlinePass } from "three/addons/postprocessing/OutlinePass.js";
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import * as Three from "three";

var scene, mesh, model1, model2; //这两个变量不要在data(){ }中定义问题即可解决。

export default {
    data() {
        return {
            // publicPath: process.env.BASE_URL,
            // mesh: null,
            camera: null,


            // scene: null,
            renderer: null,

            controls: null
        }
    },
    mounted() {
        this.init()
        window.addEventListener("click", this.onClick, false);

    },

    methods: {
        //事件函数

        onClick(event) {
            const raycaster = new THREE.Raycaster();
            const mouse = new THREE.Vector2();
            // 计算鼠标或触摸点的位置
            const threeModel = document.getElementById("container");
            const width = threeModel.offsetWidth;
            const height = threeModel.offsetHeight;
            let getClientRect = threeModel.getBoundingClientRect();
            mouse.x = ((event.clientX - getClientRect.left) / width) * 2 - 1;
            mouse.y = -((event.clientY - getClientRect.top) / height) * 2 + 1;

            console.log(event.clientX)

            // 更新射线   注意——> this.camera 是相机   定义到data里的
            raycaster.setFromCamera(mouse, this.camera);
            // 计算与所有对象的交点
            const intersects = raycaster.intersectObjects(scene.children, true);

            if (intersects.length > 0) {
                // 处理点击事件
                // intersects[0] 包含了第一个
                // 交点
                const clickedObject = intersects[0].object;
                //通过点击到该模型用名字匹配
                if (clickedObject.name === clickedObject.name) {

                    // 创建后处理对象，这里我将该对象称作  效果制作器
                    mesh = new EffectComposer(this.renderer);
                    // 创建渲染器通道
                    const renderPass = new RenderPass(scene, this.camera);
                    mesh.addPass(renderPass);
                    // 创建发光描边对象,model2可选，具体根据gltf导入时所确定的名称，对应修改
                    const outlinePass = new OutlinePass(new Three.Vector2(1000, 800), model2, this.camera);

                    // 设置发光描边颜色
                    outlinePass.visibleEdgeColor.set(0x7CFC00);
                    // 设置发光描边厚度
                    outlinePass.edgeThickness = 5;
                    // 设置发光描边强度
                    outlinePass.edgeStrength = 7;
                    // 设置闪烁频率
                    outlinePass.pulsePeriod = 2;
                    const obj = [];
                    scene.traverse(item => {
                        if (item.isMesh) {
                            obj.push(item);
                        }
                    })
                    outlinePass.selectedObjects = obj;
                    mesh.addPass(outlinePass);
                    this.renderFun();



                }
            }
        },

        // 初始化
        init() {
            this.createScene() // 创建场景
            this.loadGLTF() // 加载GLTF模型
            this.createLight() // 创建光源
            this.createCamera() // 创建相机
            this.createRender() // 创建渲染器
            this.createControls() // 创建控件对象
            this.render() // 渲染
        },
        //技术来自  http://www.webgl3d.cn/pages/637c91/
        // 1.创建三维场景
        createScene() {
            scene = new THREE.Scene()
        },
        // 加载GLTF模型对象，（别的模型需要单独修改）
        loadGLTF() {
            const loader = new GLTFLoader()
            loader.load(`../../public/adc.gltf`,
                gltf1 => {
                    model1 = gltf1.scene//用于全局控制变色时的具体对象，变色时选择model1则代表该模型变色
                    // 解决模型为黑色的问题
                    gltf1.scene.traverse(function (child) {//遍历对象，给其上色
                        if (child.isMesh) {
                            child.material.emissive = child.material.color;//emissive自发光属性，color默认值是白色
                            child.material.emissiveMap = child.material.map;//emissiveMap自发光贴图属性

                        }
                    });
                    gltf1.scene.children[0].scale.set(10, 10, 10)//调整模型整体大小用的，三个数值保持一致即可
                    scene.add(model1)
                })
            loader.load(`../gy.gltf`,
                gltf2 => {
                    model2 = gltf2.scene//用于全局控制变色时的具体对象，变色时选择model2则代表该模型变色

                    // 解决模型为黑色的问题
                    gltf2.scene.traverse(function (child) {//遍历对象，给其上色
                        if (child.isMesh) {
                            child.material.emissive = child.material.color;//emissive自发光属性，color默认值是白色
                            child.material.emissiveMap = child.material.map;//emissiveMap自发光贴图属性

                        }
                    });
                    gltf2.scene.children[0].scale.set(10, 10, 10)
                    gltf2.scene.children[0].position.x = 150//平行横向
                    gltf2.scene.children[0].position.y = 150//平行前后
                    gltf2.scene.children[0].position.z = 150//平行前后

                    scene.add(model2)
                })
        },

        // 创建光源
        createLight() {
            // 环境光
            const ambientLight = new THREE.AmbientLight(0xffffff, 0.1) // 创建环境光
            scene.add(ambientLight) // 将环境光添加到场景
            // 创建聚光灯
            const spotLight = new THREE.SpotLight(0xffffff)
            spotLight.position.set(150, 150, 150)
            spotLight.castShadow = true
            scene.add(spotLight)
        },
        // 创建相机
        createCamera() {
            //先设计坐标系
            const width = 300 // 窗口宽度
            const height = 150 // 窗口高度
            const k = width / height // 窗口宽高比
            //设计相机
            // PerspectiveCamera( fov, aspect, near, far )
            this.camera = new THREE.PerspectiveCamera(75, k, 0.1, 1000)//
            this.camera.position.set(150, 150, 150) // 设置相机位置,主要控制页面显示中的起始大小
            this.camera.lookAt(new THREE.Vector3(10, 40, 0)) // 设置相机方向


            //把相机加到三维场景中
            scene.add(this.camera)


        },
        // 创建渲染器
        createRender() {
            const element = document.getElementById('container')
            //创建WebGL渲染器
            this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
            this.renderer.setSize(element.clientWidth, element.clientHeight) // 设置渲染区域尺寸
            this.renderer.shadowMap.enabled = true // 显示阴影
            this.renderer.shadowMap.type = THREE.PCFSoftShadowMap//设置阴影效果
            this.renderer.setClearColor(null, 1) // 设置背景颜色,null就是透明色

            //three.js执行渲染命令会输出一个canvas画布(HTML元素)，你可以插入到web页面中
            element.appendChild(this.renderer.domElement)

        },

        //开始渲染
        render() {
            if (mesh) {
                //加z轴方向旋转弧度，每次旋转0.006个弧度
                mesh.rotation.z += 0.006
            }
            //把三维场景，和照相机开始渲染
            this.renderer.render(scene, this.camera)

            //页面刷新，自动重新渲染话
            requestAnimationFrame(this.render)
            this.camera.updateMatrixWorld()

        },
        renderFun() {
            mesh.render();
            window.requestAnimationFrame(this.renderFun);
        },
        // 创建控件对象
        createControls() {
            this.controls = new OrbitControls(this.camera, this.renderer.domElement)

        }
    }
}
</script>
<style>
#container {
    position: absolute;
    width: 30%;
    height: 40%;
}
</style>
